// 根据官方文档建议，几千条数据直接交前端处理合适，有处理10万条效率仍不错的案例。
"use client";
import React, { CSSProperties } from "react";
import {
  Header,
  Cell,
  Column,
  ColumnDef,
  ColumnFiltersState,
  PaginationState,
  SortingState,
  TableState,
  Updater,
  VisibilityState,
  flexRender,
  getCoreRowModel,
  getFilteredRowModel,
  getExpandedRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  useReactTable,
  ColumnPinningState,
} from "@tanstack/react-table";
import { useForm } from "react-hook-form";

import {
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";
import { Loading } from "@/components/ui/loading";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { Heading } from "@/components/ui/heading";
import { Separator } from "@/components/ui/separator";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import {
  ArrowUpDown,
  ArrowLeftRight,
  ArrowLeftToLine,
  ArrowRightToLine,
  ChevronsLeft,
  ChevronsRight,
  Pin,
  ChevronLeftIcon,
  ChevronRightIcon,
} from "lucide-react";
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
import { useTableUrlSearchParams } from "@/hooks/useTableUrlSearchParams";
import { useTableSearchParams } from "@/hooks/useTableSearchParams";
import { DropzoneFileUploader } from "@/components/ui/file-uploader";
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
// needed for table body level scope DnD setup
import {
  DndContext,
  KeyboardSensor,
  MouseSensor,
  TouchSensor,
  closestCenter,
  type DragEndEvent,
  useSensor,
  useSensors,
} from "@dnd-kit/core";
import { restrictToHorizontalAxis } from "@dnd-kit/modifiers";
import {
  arrayMove,
  SortableContext,
  horizontalListSortingStrategy,
} from "@dnd-kit/sortable";

// needed for row & cell level scope DnD setup
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";

interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData, TValue>[];
  data: TData[];
  totalCount: number; // 分片取数时不能用data.length计算页数
  defaultFilterColumn: string;
  loading?: boolean;
  initColumnVisibility?: { [key: string]: boolean }; // 不显示但row.getValue()仍然能取到值
  pageSizeOptions?: number[];
  synchroniseUrl?: boolean;
  showImportButton?: boolean;
  showExportButton?: boolean;
  showBatchSubmit?: boolean;
  onSubmitFiles?: (values: File[]) => Promise<any>;
  onBatchSubmit?: (values: any) => Promise<any>;
  onExportSubmit?: (values: any) => void;
}

const CustomDndTable: React.FC<DataTableProps<any, any>> = ({
  columns,
  data,
  totalCount,
  defaultFilterColumn,
  initColumnVisibility = {},
  pageSizeOptions = [10, 30, 50, 100, 300],
  loading = false,
  synchroniseUrl = true,
  showImportButton = false,
  showExportButton = false,
  showBatchSubmit = false,
  onSubmitFiles,
  onBatchSubmit,
  onExportSubmit,
}) => {
  const {
    pageIndex,
    pageSize,
    sorting,
    columnFilters,
    setTableUrlSearchParams,
  } = useTableUrlSearchParams();
  const {
    pageIndex: localPageIndex,
    pageSize: localPageSize,
    sorting: localSorting,
    columnFilters: localColumnFilters,
    setTableSearchParams,
  } = useTableSearchParams();
  const [pageCount, setPageCount] = React.useState<number>(0);
  const [isSubmitting, setIsSubmitting] = React.useState<boolean>(false);
  const [columnVisibility, setColumnVisibility] =
    React.useState<VisibilityState>(initColumnVisibility);
  const [columnOrder, setColumnOrder] = React.useState<string[]>(() =>
    columns.map((c) => c.id!)
  );
  const [columnPinning, setColumnPinning] = React.useState<ColumnPinningState>({
    left: ["select"],
    right: ["actions"],
  });
  const [rowSelection, setRowSelection] = React.useState({});
  const [pagination, setPagination] = React.useState(
    synchroniseUrl
      ? {
          pageIndex,
          pageSize,
        }
      : { pageIndex: localPageIndex, pageSize: localPageSize }
  );
  const [filterColumn, setFilterColumn] = React.useState<any>();
  const [multiColumnFilter, setMultiColumnFilter] = React.useState<boolean>();

  // 定义文件的最大大小限制（例如 5MB）
  const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5 MB

  // 自定义验证函数，用于检查文件大小和类型
  const fileValidator = z.instanceof(File).refine(
    (file) => {
      // 检查文件大小
      if (file.size > MAX_FILE_SIZE) {
        return false;
      }

      // 检查 MIME 类型
      const allowedMimeTypes = ["image/jpeg", "image/png"];
      if (!allowedMimeTypes.includes(file.type)) {
        return false;
      }

      // 文件通过所有检查
      return true;
    },
    {
      message: "File must be less than 5MB and must be a JPEG or PNG image.",
    }
  );

  // 定义包含文件的表单模式
  const formSchema = z.object({
    // file: fileValidator,
    files: z.any().array(),
  });

  type FormValuesT = z.infer<typeof formSchema>;

  const [isDialogOpen, setIsDialogOpen] = React.useState<boolean>();
  const defaultValues = {
    files: [],
  };
  const form = useForm<FormValuesT>({
    resolver: zodResolver(formSchema),
    defaultValues: defaultValues,
  });

  const handleFormSubmit = React.useCallback(async (values: any) => {
    // to-do 添加校验
    // form.trigger()
    if (onSubmitFiles) {
      try {
        setIsSubmitting(true);
        const result = await onSubmitFiles(values);
        console.log(result);
        setIsSubmitting(false);
      } finally {
        setIsSubmitting(false);
      }
    }
  }, []);

  React.useEffect(() => {
    if (synchroniseUrl) {
      setPageCount(Math.ceil(totalCount / (pageSize || 10)));
    } else {
      setPageCount(Math.ceil(totalCount / (localPageSize || 10)));
    }
  }, [totalCount, pageSize, localPageSize]);

  React.useEffect(() => {
    const result = columns.find((column) => {
      // console.log(column);
      // console.log(column.id);
      // column的id属性通常要明确赋值，如果没有的话会从accessorKey和header属性生成。
      return "id" in column && column.id == defaultFilterColumn;
    });
    setFilterColumn(result);
  }, [defaultFilterColumn]);

  const table = useReactTable({
    data,
    columns,
    pageCount: pageCount ?? -1,
    getCoreRowModel: getCoreRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
    // getFilteredRowModel: getFilteredRowModel(), // 客户端检索时必须项，服务端检索过滤时不用
    manualFiltering: true, // 自己服务器端检索过滤
    getExpandedRowModel: getExpandedRowModel(),
    filterFromLeafRows: true,
    maxLeafRowFilterDepth: 1,
    onColumnVisibilityChange: setColumnVisibility,
    onColumnOrderChange: setColumnOrder,
    columnResizeMode: "onChange",
    onRowSelectionChange: setRowSelection,
    onPaginationChange: (updater) => {
      setPagination((old) => {
        const newPaginationValue =
          updater instanceof Function ? updater(old) : updater;
        if (synchroniseUrl) {
          setTableUrlSearchParams({
            pageIndex: newPaginationValue.pageIndex,
            pageSize: newPaginationValue.pageSize,
          });
        } else {
          setTableSearchParams({
            pageIndex: newPaginationValue.pageIndex,
            pageSize: newPaginationValue.pageSize,
          });
        }
        return newPaginationValue;
      });
    },
    onSortingChange: (updater) => {
      const newSortingValue =
        updater instanceof Function ? updater(sorting) : updater;
      // console.log(newSortingValue);
      if (synchroniseUrl) {
        setTableUrlSearchParams({
          sorting: newSortingValue,
        });
      } else {
        setTableSearchParams({
          sorting: newSortingValue,
        });
      }
    },
    onColumnFiltersChange: (updater) => {
      const newColumnFiltersValue =
        updater instanceof Function ? updater(columnFilters) : updater;
      // console.log(newColumnFiltersValue);
      const currentFilter = newColumnFiltersValue.find(
        (item) => item.id == filterColumn.id
      );
      // console.log(currentFilter);
      // 当前检索字段有值时才能检索到，空值不会存在
      if (currentFilter) {
        if (multiColumnFilter) {
          if (synchroniseUrl && newColumnFiltersValue) {
            setTableUrlSearchParams({
              columnFilters: newColumnFiltersValue,
            });
          } else {
            setTableSearchParams({
              columnFilters: newColumnFiltersValue,
            });
          }
        } else {
          if (synchroniseUrl && newColumnFiltersValue) {
            setTableUrlSearchParams({
              columnFilters: [currentFilter],
            });
          } else {
            setTableSearchParams({
              columnFilters: [currentFilter],
            });
          }
        }
      } else {
        if (multiColumnFilter) {
          if (synchroniseUrl && newColumnFiltersValue) {
            setTableUrlSearchParams({
              columnFilters: newColumnFiltersValue,
            });
          } else {
            setTableSearchParams({
              columnFilters: newColumnFiltersValue,
            });
          }
        } else {
          if (synchroniseUrl && newColumnFiltersValue) {
            setTableUrlSearchParams({
              columnFilters: [],
            });
          } else {
            setTableSearchParams({
              columnFilters: [],
            });
          }
        }
      }
    },
    onColumnPinningChange: setColumnPinning,
    state: {
      sorting: synchroniseUrl ? sorting : localSorting,
      columnFilters: synchroniseUrl ? columnFilters : localColumnFilters,
      columnVisibility,
      columnOrder,
      columnPinning,
      rowSelection,
      pagination: synchroniseUrl
        ? { pageIndex, pageSize }
        : { pageIndex: localPageIndex, pageSize: localPageSize },
    },
    enableColumnResizing: true,
    enableMultiRowSelection: true,
    defaultColumn: {
      size: 200,
      minSize: 150,
      maxSize: 1550,
    },
    manualPagination: true,
  });

  if (filterColumn) {
    const searchValue = table
      .getColumn(filterColumn.id)
      ?.getFilterValue() as string;
    // console.log(filterColumn.id, ":", searchValue);
  }

  const getCommonPinningStyles = (column: Column<any>): CSSProperties => {
    const isPinned = column.getIsPinned();
    const isLastLeftPinnedColumn =
      isPinned === "left" && column.getIsLastColumn("left");
    const isFirstRightPinnedColumn =
      isPinned === "right" && column.getIsFirstColumn("right");

    return {
      boxShadow: isLastLeftPinnedColumn
        ? "-4px 0 4px -4px gray inset"
        : isFirstRightPinnedColumn
        ? "4px 0 4px -4px gray inset"
        : undefined,
      left: isPinned === "left" ? `${column.getStart("left")}px` : undefined,
      right: isPinned === "right" ? `${column.getAfter("right")}px` : undefined,
      opacity: isPinned ? 0.8 : 1,
      position: isPinned ? "sticky" : "relative",
      // width: `${column.getSize()}px`,
      width: `${column.columnDef.size}px`,
      zIndex: isPinned ? 1 : 0,
      minWidth: `${column.columnDef.minSize}px`,
      maxWidth: `${column.columnDef.maxSize}px`,
    };
  };

  const DraggableTableHeader = ({
    header,
  }: {
    header: Header<any, unknown>;
  }) => {
    const { column } = header;
    const { attributes, isDragging, listeners, setNodeRef, transform } =
      useSortable({
        id: header.column.id,
      });

    const draggingStyle: CSSProperties = {
      opacity: isDragging ? 0.8 : 1,
      position: "relative",
      transform: CSS.Translate.toString(transform), // translate instead of transform to avoid squishing
      transition: "width transform 0.2s ease-in-out",
      whiteSpace: "nowrap",
      width: header.column.getSize(),
      zIndex: isDragging ? 1 : 0,
    };

    return (
      <TableHead
        key={header.id}
        colSpan={header.colSpan}
        ref={setNodeRef}
        style={{
          ...Object.assign({}, getCommonPinningStyles(column), draggingStyle),
        }}
      >
        <div className="flex">
          <div className="flex flex-col">
            <div className="flex justify-center items-center">
              {header.isPlaceholder
                ? null
                : flexRender(
                    header.column.columnDef.header,
                    header.getContext()
                  )}
              {column.getCanSort() && (
                <button
                  className="border rounded px-2 mx-1"
                  onClick={() => {
                    column.toggleSorting(column.getIsSorted() === "asc");
                  }}
                >
                  <ArrowUpDown size={12} />
                </button>
              )}
              <button
                {...attributes}
                {...listeners}
                className="border rounded px-2 mx-1"
              >
                <ArrowLeftRight size="12" />
              </button>
            </div>
            {!header.isPlaceholder && header.column.getCanPin() && (
              <div className="flex gap-1 justify-center">
                {header.column.getIsPinned() !== "left" ? (
                  <button
                    className="border rounded px-2"
                    onClick={() => {
                      header.column.pin("left");
                    }}
                  >
                    <ArrowLeftToLine size="14" />
                  </button>
                ) : null}
                {header.column.getIsPinned() && (
                  <button
                    className="border rounded px-2"
                    onClick={() => {
                      header.column.pin(false);
                    }}
                  >
                    <Pin size="14" />
                  </button>
                )}
                {header.column.getIsPinned() !== "right" && (
                  <button
                    className="border rounded px-2"
                    onClick={() => {
                      header.column.pin("right");
                    }}
                  >
                    <ArrowRightToLine size="14" />
                  </button>
                )}
              </div>
            )}
          </div>
          <div
            onDoubleClick={() => {
              header.column.resetSize();
            }}
            onMouseDown={header.getResizeHandler()}
            onTouchStart={header.getResizeHandler()}
            className={`resizer ${
              header.column.getIsResizing() ? "isResizing" : ""
            } `}
          ></div>
        </div>
      </TableHead>
    );
  };

  const DragAlongCell = ({ cell }: { cell: Cell<any, unknown> }) => {
    const { column } = cell;
    const { isDragging, setNodeRef, transform } = useSortable({
      id: cell.column.id,
    });

    const draggingStyle: CSSProperties = {
      opacity: isDragging ? 0.8 : 1,
      position: "relative",
      transform: CSS.Translate.toString(transform), // translate instead of transform to avoid squishing
      transition: "width transform 0.2s ease-in-out",
      width: cell.column.getSize(),
      zIndex: isDragging ? 1 : 0,
    };

    return (
      <TableCell
        style={{
          ...Object.assign({}, getCommonPinningStyles(column), draggingStyle),
        }}
        ref={setNodeRef}
      >
        {flexRender(cell.column.columnDef.cell, cell.getContext())}
      </TableCell>
    );
  };

  // reorder columns after drag & drop
  function handleDragEnd(event: DragEndEvent) {
    const { active, over } = event;
    if (active && over && active.id !== over.id) {
      setColumnOrder((columnOrder) => {
        const oldIndex = columnOrder.indexOf(active.id as string);
        const newIndex = columnOrder.indexOf(over.id as string);
        return arrayMove(columnOrder, oldIndex, newIndex); //this is just a splice util
      });
    }
  }

  const sensors = useSensors(
    useSensor(MouseSensor, {}),
    useSensor(TouchSensor, {}),
    useSensor(KeyboardSensor, {})
  );

  // 自定义防抖函数
  function debounce<T extends any[], R>(
    func: (this: any, ...args: T) => R,
    wait: number
  ): (...args: T) => void {
    let timeout: ReturnType<typeof setTimeout> | null = null;
    return function (this: any, ...args: T): void {
      if (timeout !== null) {
        clearTimeout(timeout);
      }
      timeout = setTimeout(() => func.apply(this, args), wait);
    };
  }

  return (
    <>
      <div className="flex justify-between">
        {filterColumn && (
          <div className="flex space-x-3">
            <Select
              onValueChange={(value) => {
                console.log(value);
                const result = columns.find((column) => {
                  // console.log(column);
                  return column.id == value;
                });
                if (result) {
                  console.log(result);
                  setFilterColumn(result);
                }
              }}
            >
              <SelectTrigger className="w-[170px]">
                <SelectValue
                  placeholder={
                    filterColumn &&
                    filterColumn.header &&
                    filterColumn.header instanceof Function
                      ? filterColumn.header()
                      : filterColumn.header
                  }
                />
              </SelectTrigger>
              <SelectContent>
                {table
                  .getAllColumns()
                  .filter((column) => column.getCanFilter())
                  .map((column) => {
                    return (
                      <SelectItem
                        key={column.id}
                        value={column.id}
                        className="capitalize"
                      >
                        {column &&
                        column.columnDef.header &&
                        column.columnDef.header instanceof Function
                          ? column.columnDef.header(null as any)
                          : column.columnDef.header}
                      </SelectItem>
                    );
                  })}
              </SelectContent>
            </Select>
            {/* 当出现password输入项时，浏览器会自动找username类input并自动填值
                浏览器会寻找表单中的password输入框，自动填充之前的密码。
                Chrome等浏览器autoComplete=off不起作用。放在这里起到蜜罐
                的作用。但不能解决用户名自动填充和点击真实的密码框下拉列表的问题。
                蜜罐不能用display: "none"或visibility: "hidden"隐藏，否则失效
              */}
            <input
              type="password"
              style={{
                display: "none",
                width: "1px",
                height: "1px",
                position: "absolute",
                border: "0px",
                padding: "0px",
              }}
            />
            <Input
              placeholder={`Search ${filterColumn.id}...`}
              value={
                (table
                  .getColumn(filterColumn.id)
                  ?.getFilterValue() as string) ?? ""
              }
              onChange={(event) => {
                table
                  .getColumn(filterColumn.id)
                  ?.setFilterValue(event.target.value);
                if (synchroniseUrl) {
                  // 检索关键词变化时要将页索引重置为0
                  setTableUrlSearchParams({
                    search: event.target.value,
                    pageIndex: 0,
                  });
                } else {
                  setTableSearchParams({
                    search: event.target.value,
                    pageIndex: 0,
                  });
                }
              }}
              // 自定义和lodash的debounce都会导致Input无法输入内容，原因待查
              // onChange={debounce((event) => {
              //   table
              //     .getColumn(filterColumn.id)
              //     ?.setFilterValue(event.target.value);
              //   if (synchroniseUrl) {
              //     // 检索关键词变化时要将页索引重置为0
              //     setTableUrlSearchParams({
              //       search: event.target.value,
              //       pageIndex: 0,
              //     });
              //   } else {
              //     setTableSearchParams({
              //       search: event.target.value,
              //       pageIndex: 0,
              //     });
              //   }
              // }, 300)}
              // onChange={debounce((event) => {
              //   table
              //     .getColumn(filterColumn.id)
              //     ?.setFilterValue(event.target.value);
              //   if (synchroniseUrl) {
              //     // 检索关键词变化时要将页索引重置为0
              //     setTableUrlSearchParams({
              //       search: event.target.value,
              //       pageIndex: 0,
              //     });
              //   } else {
              //     setTableSearchParams({
              //       search: event.target.value,
              //       pageIndex: 0,
              //     });
              //   }
              // }, 0)}
              className="w-full md:max-w-sm"
            />
            <div className="flex items-center space-x-2">
              <Checkbox
                checked={multiColumnFilter}
                onCheckedChange={(value) => {
                  console.log(value);
                  setMultiColumnFilter(!multiColumnFilter);
                }}
              />
              <span className="w-[80px]">组合条件</span>
            </div>
          </div>
        )}
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button variant="outline" className="ml-auto">
              选择展示列
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            {table
              .getAllColumns()
              .filter((column) => column.getCanHide())
              .map((column) => {
                // console.log(column.columnDef);
                // console.log(column.columnDef.header);
                return (
                  <DropdownMenuCheckboxItem
                    key={column.id}
                    className="capitalize"
                    checked={column.getIsVisible()}
                    onCheckedChange={(value) =>
                      column.toggleVisibility(!!value)
                    }
                  >
                    {/* {typeof column.columnDef.header == "string"
                      ? column.columnDef.header
                      : column.id} */}
                    {column &&
                    column.columnDef &&
                    column.columnDef.header &&
                    column.columnDef.header instanceof Function
                      ? column.columnDef.header(null as any)
                      : column.columnDef.header}
                  </DropdownMenuCheckboxItem>
                );
              })}
          </DropdownMenuContent>
        </DropdownMenu>
        {showImportButton && (
          <Button
            variant="outline"
            onClick={() => setIsDialogOpen(!isDialogOpen)}
          >
            批量导入
          </Button>
        )}
        {showExportButton && (
          <Button variant="outline" onClick={onExportSubmit}>
            批量导出
          </Button>
        )}
        {showBatchSubmit && (
          <Button
            variant="outline"
            onClick={() => {
              const data = table.getSelectedRowModel();
              console.log(data);
              if (data.rows.length && onBatchSubmit) {
                onBatchSubmit(data.rows);
              }
            }}
          >
            批量提交
          </Button>
        )}
      </div>
      <DndContext
        collisionDetection={closestCenter}
        modifiers={[restrictToHorizontalAxis]}
        onDragEnd={handleDragEnd}
        sensors={sensors}
      >
        {loading ? (
          <Loading />
        ) : (
          <ScrollArea
            className="h-[calc(80vh-30px)] rounded-md border"
            style={{ position: "relative" }}
          >
            {/* <Table className="relative" style={{ width: table.getTotalSize() }}> */}
            <Table className="relative">
              <TableHeader>
                {table.getHeaderGroups().map((headerGroup) => {
                  // console.log(headerGroup);
                  return (
                    <TableRow key={headerGroup.id}>
                      {headerGroup.headers.map((header) => {
                        return (
                          <SortableContext
                            key={header.id}
                            items={columnOrder}
                            strategy={horizontalListSortingStrategy}
                          >
                            <DraggableTableHeader
                              key={header.id}
                              header={header}
                            />
                          </SortableContext>
                        );
                      })}
                    </TableRow>
                  );
                })}
              </TableHeader>
              <TableBody>
                {table.getRowModel().rows?.length ? (
                  table.getRowModel().rows.map((row) => (
                    <TableRow
                      key={row.id}
                      data-state={row.getIsSelected() && "selected"}
                    >
                      {row.getVisibleCells().map((cell) => {
                        return (
                          <SortableContext
                            key={cell.id}
                            items={columnOrder}
                            strategy={horizontalListSortingStrategy}
                          >
                            <DragAlongCell key={cell.id} cell={cell} />
                          </SortableContext>
                        );
                      })}
                    </TableRow>
                  ))
                ) : (
                  <TableRow>
                    <TableCell
                      colSpan={columns.length}
                      className="h-24 text-center"
                    >
                      暂无数据
                    </TableCell>
                  </TableRow>
                )}
              </TableBody>
            </Table>
            <ScrollBar orientation="horizontal" />
          </ScrollArea>
        )}
      </DndContext>

      <div className="flex flex-col items-center justify-end gap-2 space-x-2 py-4 sm:flex-row">
        <div className="flex w-full items-center justify-between">
          <div className="flex-1 text-sm text-muted-foreground">
            <span>选择了</span>{" "}
            {table.getFilteredSelectedRowModel().rows.length} <span>行</span>
          </div>
          <div className="flex flex-col items-center gap-4 sm:flex-row sm:gap-6 lg:gap-8">
            <div className="flex items-center space-x-2">
              <p className="whitespace-nowrap text-sm font-medium">每页</p>
              <Select
                value={`${table.getState().pagination.pageSize}`}
                onValueChange={(value) => {
                  table.setPageSize(Number(value));
                }}
              >
                <SelectTrigger className="h-8 w-[70px]">
                  <SelectValue
                    placeholder={table.getState().pagination.pageSize}
                  />
                </SelectTrigger>
                <SelectContent side="top">
                  {pageSizeOptions.map((pageSize) => (
                    <SelectItem key={pageSize} value={`${pageSize}`}>
                      {pageSize}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <p className="whitespace-nowrap text-sm font-medium">行</p>
            </div>
          </div>
        </div>
        {/* 翻页工具 */}
        <div className="flex w-full items-center justify-between gap-2 sm:justify-end">
          <div className="flex w-[100px] items-center justify-center text-sm font-medium">
            {table.getState().pagination.pageIndex + 1} / {table.getPageCount()}
          </div>
          <div className="flex items-center space-x-2">
            <Button
              aria-label="Go to first pageIndex"
              variant="outline"
              className="hidden h-8 w-8 p-0 lg:flex"
              onClick={() => table.setPageIndex(0)}
              disabled={!table.getCanPreviousPage()}
            >
              <ChevronsLeft className="h-4 w-4" aria-hidden="true" />
            </Button>
            <Button
              aria-label="Go to previous pageIndex"
              variant="outline"
              className="h-8 w-8 p-0"
              onClick={(e) => {
                e.preventDefault();
                table.previousPage();
              }}
              disabled={!table.getCanPreviousPage()}
            >
              <ChevronLeftIcon className="h-4 w-4" aria-hidden="true" />
            </Button>
            <Button
              aria-label="Go to next pageIndex"
              variant="outline"
              className="h-8 w-8 p-0"
              onClick={(e) => {
                e.preventDefault();
                table.nextPage();
              }}
              disabled={!table.getCanNextPage()}
            >
              <ChevronRightIcon className="h-4 w-4" aria-hidden="true" />
            </Button>
            <Button
              aria-label="Go to last pageIndex"
              variant="outline"
              className="hidden h-8 w-8 p-0 lg:flex"
              onClick={() => table.setPageIndex(table.getPageCount() - 1)}
              disabled={!table.getCanNextPage()}
            >
              <ChevronsRight className="h-4 w-4" aria-hidden="true" />
            </Button>
          </div>
        </div>
        {/* 批量导入文件提交文件对话框 */}
        <Dialog
          open={isDialogOpen}
          onOpenChange={() => setIsDialogOpen(!isDialogOpen)}
        >
          <DialogContent className="max-w-3xl overflow-y-auto">
            <DialogHeader>
              <DialogTitle></DialogTitle>
              <DialogDescription></DialogDescription>
            </DialogHeader>
            <div className="flex items-center justify-between">
              <Heading title="Excel批量导入数据" description={""} />
            </div>
            <Separator />
            <Form {...form}>
              <form
                onSubmit={form.handleSubmit(handleFormSubmit)}
                className="w-full space-y-8 flex flex-col justify-center"
              >
                <div className="flex flex-col gap-4">
                  <FormField
                    control={form.control}
                    name="files"
                    render={({ field }) => (
                      <FormItem>
                        <FormControl>
                          <DropzoneFileUploader
                            value={field.value}
                            onChange={field.onChange}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </div>
                <Button
                  disabled={isSubmitting}
                  className="ml-auto"
                  type="submit"
                >
                  提交
                </Button>
              </form>
            </Form>
          </DialogContent>
        </Dialog>
      </div>
    </>
  );
};

export default CustomDndTable;
